package com.github.boluo1230.wechat.service.mp.impl;

import com.github.boluo1230.wechat.constant.EnumConstant;
import com.github.boluo1230.wechat.constant.StatConstant;
import com.github.boluo1230.wechat.dao.AutoReplyKeywordsInfoDao;
import com.github.boluo1230.wechat.dao.BaseReplyInfoDao;
import com.github.boluo1230.wechat.entity.AutoReplyKeywordsInfo;
import com.github.boluo1230.wechat.entity.BaseReplyInfo;
import com.github.boluo1230.wechat.entity.EventMessage;
import com.github.boluo1230.wechat.entity.MpApp;
import com.github.boluo1230.wechat.entity.detail.KeywordDetails;
import com.github.boluo1230.wechat.entity.detail.ReplyDetails;
import com.github.boluo1230.wechat.entity.vo.MpAutoReplyInfo;
import com.github.boluo1230.wechat.service.mp.AutoReplyService;
import com.github.boluo1230.wechat.service.mp.RedisService;
import com.github.boluo1230.wechat.service.mp.SendMessageServive;
import com.github.boluo1230.wechat.util.PageHelperUtil;
import org.apache.commons.lang.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Code Farmer
 * @date 2019/10/16 17:27
 */
@Service
public class AutoReplyServiceImpl implements AutoReplyService {

    @Autowired
    private BaseReplyInfoDao baseReplyInfoDao;
    @Autowired
    private AutoReplyKeywordsInfoDao autoReplyKeywordsInfoDao;
    @Autowired
    private RedisService redisService;
    @Autowired
    private SendMessageServive sendMessageServive;

    @Override
    public boolean handleAutoReply(EventMessage message, MpApp mpApp) {
        Map<String, Boolean> allowAutoReply = new ConcurrentHashMap<String, Boolean>() {{
            put("image", false);
            put("voice", false);
            put("text", true);
            put("location", false);
            put("subscribe", true);
            put("CLICK", true);
        }};

        if (message.getMsgType().equals("event")) {
            message.setMsgType(message.getEvent());
        }

        //过滤无需判断自动回复的消息
        if (allowAutoReply.get(message.getMsgType()) == null) {
            return false;
        }

        MpAutoReplyInfo mpAutoReplyInfo = this.getMpAutoReplyInfo(mpApp.getAppId());
        //如果没有配置自动回复，或者是取消订阅消息，则直接跳过
        if (mpAutoReplyInfo == null) {
            return false;
        }

        //订阅消息，且未打开自动欢迎，跳过
        if (message.getMsgType().equals("subscribe") && (!mpAutoReplyInfo.isAddFriendReplyOpen() || !mpAutoReplyInfo.isAutoReplyOpen())) {
            return false;
        }

        //不是订阅消息，且未打开自动回复，跳过
        if (message.getMsgType().equals("'subscribe'") &&
                (!mpAutoReplyInfo.isAddFriendReplyOpen()
                        || (mpAutoReplyInfo.getAutoReplyKeywordsInfoList() == null && (!mpAutoReplyInfo.isAutoReplyOpen()))
                ) && message.getMsgType().equals("CLICK")) {
            return false;
        }

        return this.sendByMsgType(message, mpApp, mpAutoReplyInfo);
    }

    public MpAutoReplyInfo getMpAutoReplyInfo(String appId) {
        if (StringUtils.isBlank(appId)) {
            return null;
        }
        MpAutoReplyInfo mpAutoReplyInfo = redisService.getCachedMpAppAutoReplyConfig(appId);
        if (mpAutoReplyInfo == null) {
            mpAutoReplyInfo = this.getMpAutoReplyInfoFromMongo(appId);
            redisService.cacheMpAppAutoReplyConfig(mpAutoReplyInfo);
        }
        return mpAutoReplyInfo;
    }

    @Override
    public List<AutoReplyKeywordsInfo> getAutoReplyKeywordsList(String appId, Integer status) {
        return autoReplyKeywordsInfoDao.getListByAppIdAndStatus(appId, status);
    }

    @Override
    public long modifyStatus(String appId, String ruleId, Integer status) {
        return autoReplyKeywordsInfoDao.modifyStatus(appId, ruleId, status);
    }

    @Override
    public long saveAutoReplyKeywordsInfo(AutoReplyKeywordsInfo autoReplyKeywordsInfo) {
        if (autoReplyKeywordsInfo.getId() == null) {
            autoReplyKeywordsInfo.setCreateDate(new Date());
        }
        autoReplyKeywordsInfo.setUpdateDate(new Date());
        return autoReplyKeywordsInfoDao.upsert(autoReplyKeywordsInfo);
    }

    @Override
    public long saveBaseReplyInfo(BaseReplyInfo baseReplyInfo) {
//        if (StringUtils.isBlank(baseReplyInfo.getAppId())) {
//            baseReplyInfo.setCreateDate(new Date());
//        }
//        autoReplyKeywordsInfo.setUpdateDate(new Date());
        return baseReplyInfoDao.upsert(baseReplyInfo);
    }

    @Override
    public MpAutoReplyInfo getMpAutoReplyInfoOnPage(String appId, int pageNo, int pageSize) {
        MpAutoReplyInfo mpAutoReplyInfo = this.getMpAutoReplyInfo(appId);
        if (mpAutoReplyInfo != null && mpAutoReplyInfo.getAutoReplyKeywordsInfoList() != null) {
            mpAutoReplyInfo.setAutoReplyKeywordsInfoList(
                    PageHelperUtil.subList(mpAutoReplyInfo.getAutoReplyKeywordsInfoList(), pageNo, pageSize));
        }
        return mpAutoReplyInfo;
    }

    private MpAutoReplyInfo getMpAutoReplyInfoFromMongo(String appId) {
        BaseReplyInfo baseReplyInfo = baseReplyInfoDao.getOneByAppId(appId);
        MpAutoReplyInfo mpAutoReplyInfo = null;
        if (baseReplyInfo != null) {
            if (baseReplyInfo.isAddFriendReplyOpen() || baseReplyInfo.isAutoReplyOpen()) {
                List<AutoReplyKeywordsInfo> autoReplyKeywordsInfoList =
                        autoReplyKeywordsInfoDao.getListByAppId(appId, EnumConstant.Status.ONLINE.getStatus());
                mpAutoReplyInfo = new MpAutoReplyInfo(baseReplyInfo, autoReplyKeywordsInfoList);
            }
        }
        return mpAutoReplyInfo;
    }

    private boolean sendByMsgType(EventMessage message, MpApp mpApp, MpAutoReplyInfo mpAutoReplyInfo) {
        String content = message.getContent();
        String openId = message.getFromUserName();

        switch (message.getMsgType()) {
            case "CLICK":
                message.setContent(message.getEventKey());
            case "text":
                List<AutoReplyKeywordsInfo> autoReplyKeywordsInfoList = mpAutoReplyInfo.getAutoReplyKeywordsInfoList();
                if (autoReplyKeywordsInfoList != null) {
                    boolean matched = false;
                    for (int i = 0; i < autoReplyKeywordsInfoList.size(); i++) {
                        AutoReplyKeywordsInfo autoReplyKeywordsInfo = autoReplyKeywordsInfoList.get(i);
                        if (matched)
                            break;
                        List<KeywordDetails> keywordDetailsList = autoReplyKeywordsInfo.getKeywordListInfo();
                        for (int j = 0; keywordDetailsList != null && j < keywordDetailsList.size(); j++) {
                            KeywordDetails keywordDetails = keywordDetailsList.get(j);
                            if (matched || !keywordDetails.getType().equals("text")) {
                                break;
                            }
                            if ((keywordDetails.getMatchMode().equals("contain") && message.getContent().contains(keywordDetails.getContent()))
                                    || (keywordDetails.getMatchMode().equals("equal") && message.getContent().equals(keywordDetails.getContent()))
                            ) {
                                List<ReplyDetails> newReplyList = new ArrayList<>();
                                if (autoReplyKeywordsInfo.getReplyListInfo() == null || autoReplyKeywordsInfo.getReplyListInfo().size() == 0) {
                                    continue;
                                }
                                matched = true;
                                if (autoReplyKeywordsInfo.getReplyMode().equals("random_one")) {
                                    int random = (int) (Math.ceil(Math.random() * autoReplyKeywordsInfo.getReplyListInfo().size()) - 1);
                                    ReplyDetails replyInfo = autoReplyKeywordsInfo.getReplyListInfo().get(random);
                                    newReplyList.add(replyInfo);
                                } else {
                                    newReplyList.addAll(autoReplyKeywordsInfo.getReplyListInfo());
                                }

                                sendMessageServive.sendReplyList(mpApp, openId, newReplyList);

                                if (StatConstant.ENABLE_AUTO_REPLY_STAT) {
                                    this.statAutoReply(mpApp.getAppId(), openId, autoReplyKeywordsInfo.getId(), autoReplyKeywordsInfo.getRuleName());
                                }
                            }
                        }
                    }
                }
        }
        return message.getMsgType() == null;
    }

    //todo  回复统计
    private void statAutoReply(String appId, String openId, ObjectId id, String ruleName) {
    }
}
